package com.xiaoxu.intranetweb.mybatisplusSzappdb.timerTasks;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaoxu.intranetweb.mybatisplusSzappdb.business.log.SysLogBu;
import com.xiaoxu.intranetweb.mybatisplusSzappdb.entity.CProductsInfo;
import com.xiaoxu.intranetweb.mybatisplusSzappdb.entity.CWeightSheets;
import com.xiaoxu.intranetweb.mybatisplusSzappdb.entity.SysDic;
import com.xiaoxu.intranetweb.mybatisplusSzappdb.service.ISysDicService;
import com.xiaoxu.intranetweb.mybatisplusSzappdb.service.impl.CProductsInfoServiceImpl;
import com.xiaoxu.intranetweb.mybatisplusSzappdb.service.impl.CWeightSheetsServiceImpl;
import com.xiaoxu.intranetweb.util.StringUtils;
import com.xiaoxu.intranetweb.util.WebServiceClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringEscapeUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.xml.soap.SOAPException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class ToEamSystem {
    @Autowired
    private CWeightSheetsServiceImpl cWeightSheetsService;
    @Autowired
    private SysLogBu sysLogBu;
    @Autowired
    private ISysDicService sysDicService;
    @Autowired
    private WebServiceClient webServiceClient;
    @Autowired
    private CProductsInfoServiceImpl productsInfoService;

    // 产品映射关系
    private static final Map<String, String> PRODUCT_MAPPING;
    static {
        Map<String, String> map = new HashMap<>();
        map.put(".石灰石粉", "石灰石粉");
        map.put(".石灰石", "石灰石");
        map.put(".二期石灰石", "石灰石");
        PRODUCT_MAPPING = Collections.unmodifiableMap(map);
    }

    @Scheduled(fixedDelay = 60000)
    public void toEamSystemFmh() {
        // 检查上传开关
        if (!isUploadEnabled()) {
            log.info("EAM上传功能已关闭");
            return;
        }
        try {
            executeEamUpload();
        } catch (Throwable t) { // 捕获所有异常，包括Error
            sysLogBu.logRecord("EAM上传异常", "toEamSystem", "异常: " + t.getMessage(), "huarunfuyang");
        }
    }

    // 将核心逻辑提取到单独方法
    private void executeEamUpload() {
        String wsdlUrl = getWsdlUrl();
        if (StringUtils.isBlank(wsdlUrl)) {
            sysLogBu.logRecord("上传EAM异常", "toEamSystem", "未找到接口地址配置！", "huarunfuyang");
            return;
        }

        // 直接查询需要上传的数据
        List<CWeightSheets> uploadList = queryUploadData();
        if (uploadList.isEmpty()) {
            log.info("无数据需要上传");
            return;
        }

        log.info("任务开始上传{}条数据到EAM系统...", uploadList.size());

        // 单线程顺序处理每条记录
        for (CWeightSheets record : uploadList) {
            try {
                processSingleRecord(record, wsdlUrl);
            } catch (Exception e) {
                log.error("任务处理记录[{}]失败", record.getWeishtSheetno(), e);
                webServiceClient.reset();
                // 记录失败但不中断整个任务
            }
        }
    }

    private List<CWeightSheets> queryUploadData() {
        List<CWeightSheets> result = new ArrayList<>();

        // 查询粉煤灰数据
        List<String> fmhProducts = queryFmhProducts();
        if (!fmhProducts.isEmpty()) {
            result.addAll(queryPendingFmhData(fmhProducts));
        }

        // 查询石灰石数据
        result.addAll(queryShsData());

        return result;
    }

    private List<String> queryFmhProducts() {
        try {
            QueryWrapper<CProductsInfo> query = new QueryWrapper<>();
            query.in("PDTINF_CLASS", "1");
            query.eq("PDTINF_DELETED", 0);
            return productsInfoService.list(query).stream()
                    .map(CProductsInfo::getPdtinfPdt)
                    .distinct()
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("查询粉煤灰产品异常: {}", e.getMessage());
            return Collections.emptyList();
        }
    }

    private List<CWeightSheets> queryPendingFmhData(List<String> productList) {
        try {
            QueryWrapper<CWeightSheets> query = new QueryWrapper<>();
            query.eq("WEISHT_DELETED", 0);
            query.ne("WEISHT_NET_WGHT", 0);
            query.isNotNull("WEISHT_FULL_TM");
            query.isNotNull("WEISHT_GROSS_WGHT");
            query.eq("DownedID11", 0);
            query.notLike("WEISHT_PRODUCT", ".");
            query.in("WEISHT_PRODUCT", productList);
            query.eq("WEISHT_BACKED", 1);
            query.last("limit 90");
            return cWeightSheetsService.list(query);
        } catch (Exception e) {
            log.error("查询待上传粉煤灰数据异常: {}", e.getMessage());
            return Collections.emptyList();
        }
    }

    private List<CWeightSheets> queryShsData() {
        try {
            QueryWrapper<CWeightSheets> query = new QueryWrapper<>();
            query.eq("WEISHT_DELETED", 0);
            query.ne("WEISHT_NET_WGHT", 0);
            query.isNotNull("WEISHT_FULL_TM");
            query.isNotNull("WEISHT_TARE");
            query.eq("WEISHT_BACKED", 1);
            query.eq("DownedID11", 0);
            query.in("WEISHT_PRODUCT", PRODUCT_MAPPING.keySet());
            query.last("limit 10");

            return cWeightSheetsService.list(query).stream()
                    .peek(this::processShsRecord)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("查询石灰石数据异常: {}", e.getMessage());
            return Collections.emptyList();
        }
    }

    private void processShsRecord(CWeightSheets record) {
        record.setWeishtCo(record.getWeishtCoSupply());
        String mappedProduct = PRODUCT_MAPPING.get(record.getWeishtProduct());
        if (mappedProduct != null) {
            record.setWeishtProduct(mappedProduct);
        }
    }

    private void processSingleRecord(CWeightSheets record, String wsdlUrl) throws Exception {
        validateData(record);
        log.info("正在上传单号【{}】, 产品: {}, 净重: {} , 车号：{}", record.getWeishtSheetno(), record.getWeishtProduct(), record.getWeishtNetWght(),record.getWeishtTruckno());
        String xmlData = buildRequestXml(record);
        String response = webServiceClient.callWebService(wsdlUrl, "upload", xmlData);
        handleResponse(response, record);
        log.info("单号【{}】上传成功", record.getWeishtSheetno());
    }

    private void validateData(CWeightSheets record) {
        if (record.getWeishtGrossWght() == null ||
                record.getWeishtTare() == null ||
                record.getWeishtNetWght() == null) {
            throw new RuntimeException("重量数据不完整");
        }

        BigDecimal calculated = record.getWeishtGrossWght().subtract(record.getWeishtTare());
        BigDecimal difference = calculated.subtract(record.getWeishtNetWght()).abs();
        if (difference.compareTo(new BigDecimal("0.001")) > 0) {
            throw new RuntimeException(String.format("重量校验失败(毛重%s-皮重%s≠净重%s)",
                    record.getWeishtGrossWght(), record.getWeishtTare(), record.getWeishtNetWght()));
        }
    }

    private String buildRequestXml(CWeightSheets record) {
        return String.format("<upload>" +
                        "<servicename>FCPXSMX</servicename>" +
                        "<partnerid>ERP</partnerid>" +
                        "<sign>48F98054E9D0056D9230BDE0A308AC25</sign>" +
                        "<data><fcpmxs><fcpmx>" +
                        "<cnum>%s</cnum>" +
                        "<createby>阜阳华润过磅系统</createby>" +
                        "<createdate>%s</createdate>" +
                        "<jz>%.2f</jz>" +
                        "<kcczsj>%s</kcczsj>" +
                        "<mz>%.2f</mz>" +
                        "<zcczsj>%s</zcczsj>" +
                        "<pz>%.2f</pz>" +
                        "<gys>%s</gys>" +
                        "<ysfs>%s</ysfs>" +
                        "<jzjhk>%.2f</jzjhk>" +
                        "<unitcost></unitcost>" +
                        "<linecost></linecost>" +
                        "<sourcenumber>%s</sourcenumber>" +
                        "</fcpmx></fcpmxs></data></upload>",
                record.getWeishtTruckno(),
                formatDate(record.getWeishtEmptyTm()),
                record.getWeishtNetWght(),
                formatDate(record.getWeishtEmptyTm()),
                record.getWeishtGrossWght(),
                formatDate(record.getWeishtFullTm()),
                record.getWeishtTare(),
                record.getWeishtCo(),
                record.getWeishtProduct(),
                record.getWeishtNetWght(),
                record.getWeishtSheetno());
    }

    private String formatDate(LocalDateTime dateTime) {
        return dateTime != null ? dateTime.toString().replace("T", " ") : "";
    }

    private void handleResponse(String soapResponse, CWeightSheets record) throws DocumentException {
        Document doc = new SAXReader().read(new StringReader(soapResponse));
        Element body = doc.getRootElement().element("Body");
        if (body == null) throw new RuntimeException("无效响应: 缺少Body节点");

        Element response = body.element("uploadResponse");
        if (response == null) throw new RuntimeException("无效响应: 缺少uploadResponse节点");

        String outContent = Optional.ofNullable(response.element("out"))
                .map(Element::getText)
                .orElseThrow(() -> new RuntimeException("无效响应: 缺少out节点"));

        String decodedXml = StringEscapeUtils.unescapeXml(outContent);
        Document resultDoc = new SAXReader().read(new StringReader(decodedXml));

        String resultCode = Optional.ofNullable(resultDoc.getRootElement().elementText("resultcode"))
                .orElseThrow(() -> new RuntimeException("无效响应: 缺少resultcode"));

        String resultMsg = Optional.ofNullable(resultDoc.getRootElement().elementText("resultmsg"))
                .orElse("无错误信息");

        if (!"1".equals(resultCode)) {
            throw new RuntimeException("EAM系统返回错误: " + resultMsg);
        }

        // 更新数据库状态
        CWeightSheets update = new CWeightSheets();
        update.setId(record.getId());
        update.setDownedID11(1);
        cWeightSheetsService.updateById(update);
    }

    private boolean isUploadEnabled() {
        try {
            QueryWrapper<SysDic> query = new QueryWrapper<>();
            query.eq("DIC_TYPE", "toEamSystem");
            query.eq("DIC_KEY", "ifon");
            SysDic dic = sysDicService.getOne(query);
            return dic != null && "1".equals(dic.getDicVal());
        } catch (Exception e) {
            log.error("检查上传开关异常: {}", e.getMessage());
            return false;
        }
    }

    private String getWsdlUrl() {
        try {
            QueryWrapper<SysDic> query = new QueryWrapper<>();
            query.eq("DIC_TYPE", "toEamSystem");
            query.eq("DIC_KEY", "fmh");
            SysDic dic = sysDicService.getOne(query);
            return dic != null ? dic.getDicVal() : null;
        } catch (Exception e) {
            log.error("获取接口地址异常: {}", e.getMessage());
            return null;
        }
    }
    @Autowired
    private OrderedExcelToTextExporter orderedExcelToTextExporter;
    public void setValue() {
        String excelPath = "D:\\汽车衡系统上传阜阳华润电力有限公司的数据.xlsx";
        String outputPath = "D:\\1.txt";
        try {
            orderedExcelToTextExporter.exportOrderedWeishtCo(excelPath, outputPath);
        } catch (Exception e) {
            log.error("Excel导出异常: {}", e.getMessage());
        }
    }

}